﻿Imports EvoLib.UDPSocket
Imports System.Runtime.InteropServices

Namespace Socket.ClusterComms

    Module UDPBrocast

        Private mSock() As UDPBroadcastSocket
        Private bIncompleteData() As Byte

        Public Function Init(ByVal hosts() As String) As Boolean

            Dim i As Integer

            ReDim mSock(hosts.Length - 1)

            For Each host As String In hosts

                mSock(i) = New UDPBroadcastSocket(Globals.iniServer.GetInteger("SERVER", "UDPBROADCASTPORT", Globals.UDPBroadcastPort))
                System.Windows.Forms.Application.DoEvents()

                If Not mSock(i).IsValidSocket Then Return False

                AddHandler mSock(i).OnRecieveData, AddressOf mSock_OnRecieveData
                AddHandler mSock(i).OnError, AddressOf mSock_OnError
                i += 1

            Next

            Return True

        End Function

        Public Sub Shutdown()

            'If Globals.bDebugMode Then Exit Sub

            For Each sock As UDPBroadcastSocket In mSock
                If Not sock Is Nothing Then
                    If sock.IsValidSocket Then sock.Dispose()
                End If
            Next

        End Sub

        Public Sub SendData(bData() As Byte)

            'If Globals.bDebugMode Then Exit Sub

            For Each sock As UDPBroadcastSocket In mSock

                sock.SendData(bData)

            Next

        End Sub

        Private Sub mSock_OnRecieveData(ByRef bData() As Byte, ByRef bytes As Integer)

            'If Globals.bDebugMode Then Exit Sub

            If bData Is Nothing Then Exit Sub
            If bytes = 0 Then Exit Sub

            If Not bIncompleteData Is Nothing Then
                If bIncompleteData.Length > 0 Then

                    Dim bTemp() As Byte
                    ReDim bTemp(bytes + bIncompleteData.Length - 1)
                    Array.Copy(bIncompleteData, 0, bTemp, 0, bIncompleteData.Length)
                    Array.Copy(bData, 0, bTemp, bIncompleteData.Length, bytes)

                    bIncompleteData = Nothing

                    bytes += bIncompleteData.Length
                    ReDim bData(bytes + 1)
                    Array.Copy(bTemp, 0, bData, 0, bytes)

                    bTemp = Nothing

                End If
            End If

            Dim info As New Packet
            Dim struct() As Byte = Nothing

            Dim ret As ParsePacketCode

            Try

                If bytes >= (Marshal.SizeOf(GetType(RawPacket)) + 1) Then
                    ret = ParsePacket(bData, info, struct)
                Else
                    ret = ParsePacketCode.Incomplete
                End If

            Catch ex As System.NullReferenceException
                Debug.Print("Handled a NullReferenceException in onRecieveData")
                ret = ParsePacketCode.Incomplete
            Catch ex As Exception
                Debug.Print("Handled an Exception in onRecieveData")
                ret = ParsePacketCode.PacketError
            End Try

            If ret = ParsePacketCode.NoData Then
                Exit Sub
            ElseIf ret = ParsePacketCode.PacketError Then
                Debug.Print("UDPClient: ParsePacket returned PacketError")
                If Not bData Is Nothing Then
                    If bData.Length > 0 Then
                        Debug.Print("UDPClient: Recieved Incomplete Data!!!")
                        ReDim bIncompleteData(bData.Length - 1)
                        Array.Copy(bData, 0, bIncompleteData, 0, bData.Length)
                    End If
                End If

            ElseIf ret = ParsePacketCode.Incomplete Then
                If Not bData Is Nothing Then
                    If bData.Length > 0 Then
                        Debug.Print("UDPClient: Recieved Incomplete Data!!!")
                        ReDim bIncompleteData(bData.Length - 1)
                        Array.Copy(bData, 0, bIncompleteData, 0, bData.Length)
                    End If
                End If

            ElseIf ret = ParsePacketCode.OK Then

                'START DEBUG OUTPUT CODE

                If Globals.bDebugMode Then
                    Dim txt As String = "===[SERVER SOCKET(UDP Broadcast) > DATA IN]====================================================" & vbCrLf
                    txt &= "     UNAME: " & info.Username & vbCrLf
                    'NOTE: This line is server based and must be changed for correct output
                    txt &= "    PACKET: " & CType(info.PacketType, GamePacketType).ToString & vbCrLf
                    txt &= "    OPCODE: " & info.PacketOpCode.ToString & vbCrLf & vbCrLf

                    If Not struct Is Nothing Then
                        txt &= "STRUCT BYTES:" & vbCrLf

                        Dim tmp As String
                        Dim asciitxt As String = ""
                        Dim i As Integer
                        Dim c As Integer
                        Dim tmpbyte(0) As Byte

                        For i = 0 To struct.Length - 1

                            tmp = struct(i)
                            Do Until tmp.Length = 3
                                tmp = " " & tmp
                            Loop

                            If tmp = 0 Then
                                txt &= "  . "
                            Else
                                txt &= " " & tmp
                            End If

                            If struct(i) < 32 Then
                                asciitxt &= "."
                            Else
                                tmpbyte(0) = struct(i)
                                asciitxt &= System.Text.Encoding.ASCII.GetString(tmpbyte)
                            End If

                            c += 1
                            If c = 20 Then
                                c = 0
                                txt &= "  " & asciitxt & vbCrLf
                                asciitxt = ""
                            ElseIf c = 10 Then
                                asciitxt &= "   "
                                txt &= "    "
                            End If

                        Next

                        If c < 10 Then txt = txt & "    "
                        If c > 0 Then txt &= "  " & Space((20 - c) * 4) & asciitxt & vbCrLf

                        txt &= struct.Length & " bytes" & vbCrLf & vbCrLf

                    End If

                    Debug.Print(txt)

                End If

                'STOP DEBUG OUTPUT CODE

                Packets.UDP.PacketIn(info, struct)

                If Not bData Is Nothing Then
                    Call mSock_OnRecieveData(bData, bData.Length)
                End If

            Else
                Debug.Print("UDPClient: ParsePacket returned an invalid value")
            End If

        End Sub

        Public Sub mSock_OnError(ByVal ex As Exception)

            If Globals.bDebugMode Then

                Debug.Print("UDP ERROR: " & ex.ToString)

            End If

        End Sub

    End Module

End Namespace
